package com.tuanbiao.ui;

import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Intent;
import android.graphics.Rect;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.View;
import android.view.WindowManager;
import android.view.animation.LinearInterpolator;
import android.widget.CompoundButton;
import android.widget.ImageView;

import androidx.fragment.app.Fragment;

import com.abiao.lib_utils.SizeUtils;
import com.ff.qrcode.library.CaptureCallback;
import com.ff.qrcode.library.camera.CameraManager;
import com.ff.qrcode.library.decode.DecodeThread;
import com.ff.qrcode.library.utils.CaptureActivityHandler;
import com.ff.qrcode.library.utils.InactivityTimer;
import com.google.zxing.Result;
import com.tuanbiao.R;
import com.tuanbiao.base.BaseActivity;
import com.tuanbiao.databinding.ActivityCaptureBinding;
import com.tuanbiao.transformers.SchedulerTransformer;
import com.tuanbiao.utils.BeepManager;
import com.tuanbiao.utils.Utils;

import java.io.IOException;

import io.reactivex.Observable;
import io.reactivex.ObservableOnSubscribe;
import io.reactivex.Observer;
import io.reactivex.disposables.CompositeDisposable;
import io.reactivex.disposables.Disposable;
import timber.log.Timber;

/**
 * description:
 * author: FF
 * time: 2019/3/15 22:06
 */
public class CaptureActivity extends BaseActivity<ActivityCaptureBinding> implements CaptureCallback, SurfaceHolder.Callback {

    protected CompositeDisposable mCompositeDisposable;
    private ObjectAnimator objectAnimator; // 属性动画
    private boolean isPause; // 是否暂停

    private InactivityTimer inactivityTimer; // 计时器
    private BeepManager beepManager; // 蜂鸣器
    private CaptureActivityHandler handler;
    private Rect mCropRect; // 矩形
    private CameraManager cameraManager; // 相机管理类
    private boolean isHasSurface; // SurfaceView控件是否存在，surfaceCreated

    private ProgressDialog dialog;// 扫描相册加载框

    public static Intent createIntent(Fragment fragment) {
        return new Intent(fragment.getActivity(), CaptureActivity.class);
    }

    @Override
    protected void initData() {
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
        initScan();
    }

    @Override
    protected ActivityCaptureBinding getBindingView() {
        return ActivityCaptureBinding.inflate(getLayoutInflater());
    }

    @Override
    protected void initView() {
// 闪光灯控制
        binding.tbLight.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                if (isChecked) {
                    binding.tvLight.setText("关灯");
                    Utils.openFlashlight(cameraManager);
                } else {
                    binding.tvLight.setText("开灯");
                    Utils.closeFlashlight();
                }
            }
        });

        // 打开相册
        binding.llAlbum.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // 打开相册，做权限判断
                Utils.openAlbum(CaptureActivity.this);
            }
        });
    }

    // 扫码初始化
    private void initScan() {
        ImageView scanLine = findViewById(R.id.scan_line);

        // 扫描线性动画(属性动画可暂停)
        float curTranslationY = scanLine.getTranslationY();
        objectAnimator = ObjectAnimator.ofFloat(scanLine, "translationY",
                curTranslationY, SizeUtils.dp2px(170));
        // 动画持续的时间
        objectAnimator.setDuration(4000);
        // 线性动画 Interpolator 匀速
        objectAnimator.setInterpolator(new LinearInterpolator());
        // 动画重复次数
        objectAnimator.setRepeatCount(ObjectAnimator.INFINITE);
        // 动画如何重复，从下到上，还是重新开始从上到下
        objectAnimator.setRepeatMode(ValueAnimator.RESTART);
    }

    @Override
    protected void onResume() {
        super.onResume();
        startScan();
    }

    @Override
    protected void onPause() {
        pauseScan();
        super.onPause();
    }

    // 开始扫描
    private void startScan() {
        inactivityTimer = new InactivityTimer(this);
        beepManager = new BeepManager(this);

        if (isPause) {
            // 如果是暂停，扫描动画应该要暂停
            objectAnimator.resume();
            isPause = false;
        } else {
            // 开始扫描动画
            objectAnimator.start();
        }

        // 初始化相机管理
        cameraManager = new CameraManager(this);
        handler = null; // 重置handler
        if (isHasSurface) {
            initCamera(binding.capturePreview.getHolder());
        } else {
            // 等待surfaceCreated来初始化相机
            binding.capturePreview.getHolder().addCallback(this);
        }
        // 开启计时器
        if (inactivityTimer != null) {
            inactivityTimer.onResume();
        }
    }

    // 暂停扫描
    private void pauseScan() {
        if (handler != null) {
            // handler退出同步并置空
            handler.quitSynchronously();
            handler = null;
        }
        // 计时器的暂停
        if (inactivityTimer != null) {
            inactivityTimer.onPause();
        }
        // 关闭蜂鸣器
        beepManager.close();
        // 关闭相机管理器驱动
        cameraManager.closeDriver();
        if (!isHasSurface) {
            // remove等待
            binding.capturePreview.getHolder().removeCallback(this);
        }
        // 动画暂停
        objectAnimator.pause();
        isPause = true;
    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        if (holder == null) {
            Log.e(TAG, "surfaceCreated: SurfaceHolder is null");
            return;
        }

        if (!isHasSurface) {
            isHasSurface = true;
            initCamera(holder);
        }
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {

    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        isHasSurface = false;
    }

    // 初始化相机
    private void initCamera(SurfaceHolder surfaceHolder) {
        if (surfaceHolder == null) {
            throw new IllegalStateException("SurfaceHolder is null");
        }
        if (cameraManager.isOpen()) {
            Log.e(TAG, "surfaceCreated: camera is open");
            return;
        }

        try {
            cameraManager.openDriver(surfaceHolder);
            if (handler == null) {
                handler = new CaptureActivityHandler(this, cameraManager, DecodeThread.ALL_MODE);
            }
            initCrop();
        } catch (IOException ioe) {
            Log.w(TAG, ioe);
            Utils.displayFrameworkBugMessageAndExit(this);
        } catch (RuntimeException e) {
            // Barcode Scanner has seen crashes in the wild of this variety:
            // java.lang.RuntimeException: Fail to connect to camera service
            Log.w(TAG, "Unexpected error initializing camera", e);
            Utils.displayFrameworkBugMessageAndExit(this);
        }
    }

    // 初始化截取的矩形区域
    private void initCrop() {
        // 获取相机的宽高
        int cameraWidth = cameraManager.getCameraResolution().y;
        int cameraHeight = cameraManager.getCameraResolution().x;

        // 获取布局中扫描框的位置信息
        int[] location = new int[2];
        binding.captureCropView.getLocationInWindow(location);

        int cropLeft = location[0];
        int cropTop = location[1] - Utils.getStatusBarHeight(this);

        // 获取截取的宽高
        int cropWidth = binding.captureCropView.getWidth();
        int cropHeight = binding.captureCropView.getHeight();

        // 获取布局容器的宽高
        int containerWidth = binding.captureContainer.getWidth();
        int containerHeight = binding.captureContainer.getHeight();

        // 计算最终截取的矩形的左上角顶点x坐标
        int x = cropLeft * cameraWidth / containerWidth;
        // 计算最终截取的矩形的左上角顶点y坐标
        int y = cropTop * cameraHeight / containerHeight;

        // 计算最终截取的矩形的宽度
        int width = cropWidth * cameraWidth / containerWidth;
        // 计算最终截取的矩形的高度
        int height = cropHeight * cameraHeight / containerHeight;

        // 生成最终的截取的矩形
        mCropRect = new Rect(x, y, width + x, height + y);
    }

    @Override
    public Rect getCropRect() {
        return mCropRect;
    }

    @Override
    public Handler getHandler() {
        return handler;
    }

    @Override
    public CameraManager getCameraManager() {
        return cameraManager;
    }

    @Override
    public void handleDecode(Result result, Bundle bundle) {
        // 扫码成功之后回调的方法
        if (inactivityTimer != null) {
            inactivityTimer.onActivity();
        }
        // 播放蜂鸣声
        beepManager.playBeepSoundAndVibrate();

        // 将扫码的结果返回到MainActivity
        Intent intent = new Intent();
        intent.putExtra(Utils.BAR_CODE, result.getText());
        Utils.setResultAndFinish(CaptureActivity.this, RESULT_OK, intent);
    }


    @Override
    protected void onActivityResult(int requestCode, int resultCode, final Intent data) {
        // 相册返回
        if (requestCode == Utils.SELECT_PIC_KITKAT // 4.4及以上图库
                && resultCode == Activity.RESULT_OK) {
            showProgressDialog();
            Observable.create((ObservableOnSubscribe<Intent>) emitter -> {
                        Uri uri = data.getData();
                        String path = Utils.getPath(CaptureActivity.this, uri);
                        Result result = Utils.scanningImage(path);
                        if (result == null) {
                            emitter.onError(new Throwable("未发现二维码/条形码"));
                        } else {
                            Intent intent = new Intent();
                            // 数据返回
                            intent.putExtra(Utils.BAR_CODE, Utils.recode(result.getText()));
                            emitter.onNext(intent);
                        }
                        emitter.onComplete();
                    }).compose(new SchedulerTransformer<>())
                    .subscribe(new Observer<Intent>() {
                        @Override
                        public void onSubscribe(Disposable d) {
                            addDispose(d);
                        }

                        @Override
                        public void onNext(Intent result) {
                            Timber.i("onNext#"+result);
                            dismissProgressDialog();
                            Utils.setResultAndFinish(CaptureActivity.this, RESULT_OK, result);
                        }

                        @Override
                        public void onError(Throwable e) {
                            dismissProgressDialog();
                            Timber.i("onError#"+e.getMessage());
                            showShort(e.getMessage());
                        }

                        @Override
                        public void onComplete() {
                            Timber.i("onComplete");
                            dismissProgressDialog();
                        }
                    });
        }
        super.onActivityResult(requestCode, resultCode, data);
    }

    @Override
    public void onBackPressed() {
        Utils.setResultAndFinish(CaptureActivity.this, RESULT_OK, new Intent());
        super.onBackPressed();
    }

    private void showProgressDialog() {
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                if (dialog == null) {
                    dialog = new ProgressDialog(CaptureActivity.this);
                    dialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
                }
                dialog.setMessage("扫描中");    //设置内容
                dialog.setCancelable(false);//点击屏幕和按返回键都不能取消加载框
                dialog.show();
            }
        });
    }

    private void dismissProgressDialog() {
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                if (dialog != null) {
                    dialog.dismiss();
                }
            }
        });
    }

    @Override
    protected void onDestroy() {
        dismissProgressDialog();
        if (objectAnimator != null) {
            objectAnimator.end();
        }
        if (inactivityTimer != null) {
            inactivityTimer.shutdown();
        }
        unDispose();
        super.onDestroy();
    }

    /**
     * 将 {@link Disposable} 添加到 {@link CompositeDisposable} 中统一管理
     * 可在 {@link Activity#onDestroy()} 中使用 {@link #unDispose()} 停止正在执行的 RxJava 任务,避免内存泄漏
     * 目前框架已使用 {@link RxLifecycle} 避免内存泄漏,此方法作为备用方案
     *
     * @param disposable
     */
    public void addDispose(Disposable disposable) {
        if (mCompositeDisposable == null) {
            mCompositeDisposable = new CompositeDisposable();
        }
        mCompositeDisposable.add(disposable);//将所有 Disposable 放入容器集中处理
    }

    /**
     * 停止集合中正在执行的 RxJava 任务
     */
    public void unDispose() {
        if (mCompositeDisposable != null) {
            mCompositeDisposable.clear();//保证 Activity 结束时取消所有正在执行的订阅
        }
    }
}
